package com.lagou.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;


@Activate(group = {CommonConstants.CONSUMER,CommonConstants.PROVIDER})
public class DubboInvokeFilter   implements Filter, Runnable {

    //时间戳对60取余，得到60组请求
    private static volatile Object[] requestArrayInOneMinute;
    
    //总请求数
    private static volatile AtomicInteger totalRequestCount;
    
    //用于统计时间的数组,初始化为2000个元素，存储1-2000毫秒响应的数量
    private static volatile AtomicInteger[] timeStatisticsArr;

    public DubboInvokeFilter() {
        totalRequestCount = new AtomicInteger(0);
        timeStatisticsArr = new AtomicInteger[2000];
        requestArrayInOneMinute = new Object[60];
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
        scheduledThreadPool.scheduleAtFixedRate(this::run, 5, 5, TimeUnit.SECONDS);
    }
    
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime  = System.currentTimeMillis();
        int group = (int) (startTime%60);
        try {
            // 执行方法
            return  invoker.invoke(invocation);
        } finally {
            int timeCost = (int) (System.currentTimeMillis()-startTime);
            //System.out.println(Thread.currentThread().getName()+ " invoke time:"+ timeCost + "毫秒");
            
            //初始化请求信息
            RequestInfo requestInfo = new RequestInfo();
            String methodName = invocation.getMethodName();
            requestInfo.setMethodName(methodName);
            requestInfo.setTimeCost(timeCost);
            requestInfo.setStartTime(startTime);
            //记录请求数据
            Map<String, List<RequestInfo>> requestMapInOneSeconds = (Map<String, List<RequestInfo>>) requestArrayInOneMinute[group];
            if(requestMapInOneSeconds==null) {
                requestMapInOneSeconds = new HashMap<>(16);
                List<RequestInfo> requestInfos = new ArrayList<>(300);
                //记录请求
                requestInfos.add(requestInfo);
                totalRequestCount.incrementAndGet();
                if(timeStatisticsArr[requestInfo.getTimeCost()]==null) {
                    timeStatisticsArr[requestInfo.getTimeCost()] = new AtomicInteger(0);
                }
                timeStatisticsArr[requestInfo.getTimeCost()].incrementAndGet();
                requestMapInOneSeconds.put(methodName, requestInfos);
                requestArrayInOneMinute[group]=requestMapInOneSeconds;
            } else {
                if(requestMapInOneSeconds.containsKey(methodName)) {
                    List<RequestInfo> requestInfos = requestMapInOneSeconds.get(methodName);
                    if(startTime-requestInfos.get(0).getStartTime()>=60000) {
                        //当前请求与记录里的请求时间相差60s以上，清理前一分钟该秒数的数据
                        for(RequestInfo r :requestInfos) {
                            totalRequestCount.decrementAndGet();
                            timeStatisticsArr[r.getTimeCost()].decrementAndGet();
                        }
                        requestInfos = new ArrayList<>(300);
                        requestMapInOneSeconds.put(methodName, requestInfos);
                    }
                    //记录请求
                    requestInfos.add(requestInfo);
                    totalRequestCount.incrementAndGet();
                    if(timeStatisticsArr[requestInfo.getTimeCost()]==null) {
                        timeStatisticsArr[requestInfo.getTimeCost()] = new AtomicInteger(0);
                    }
                    timeStatisticsArr[requestInfo.getTimeCost()].incrementAndGet();
                } else {
                    List<RequestInfo> requestInfos = new ArrayList<>(300);
                    //记录请求
                    requestInfos.add(requestInfo);
                    totalRequestCount.incrementAndGet();
                    if(timeStatisticsArr[requestInfo.getTimeCost()]==null) {
                        timeStatisticsArr[requestInfo.getTimeCost()] = new AtomicInteger(0);
                    }
                    timeStatisticsArr[requestInfo.getTimeCost()].incrementAndGet();
                    requestMapInOneSeconds.put(methodName, requestInfos);
                }
            }
        }

    }
    
    @Override
    public void run() {
        int tp90=0;
        int tp50=0;
        int temp=0;
        System.out.println("============================");
        System.out.println("总请求数："+totalRequestCount);
        //遍历存储0到1000毫秒响应数的数组
        for(int i=0; i<1000; i++) {
            if(timeStatisticsArr[i]!=null) {
                temp = temp + timeStatisticsArr[i].intValue();
            }
            if(temp>=totalRequestCount.intValue()*0.5 && tp50==0) {
                tp50 = i;
            }
            if(temp>=totalRequestCount.intValue()*0.9) {
                tp90 = i;
                break;
            }
        }
        System.out.println("tp50："+ tp50);
        System.out.println("tp90："+ tp90);
    }
}
